package com.unicloud.medical.oss.client.util;

import com.unicloud.medical.oss.common.enums.ErrorEnum;
import com.unisound.medical.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.Map;
import java.util.Objects;

@Slf4j
public class RestUtil {
    private static final RestTemplate REST_TEMPLATE;

    static {
        OkHttp3ClientHttpRequestFactory requestFactory = new OkHttp3ClientHttpRequestFactory();
        requestFactory.setConnectTimeout(300000);
        requestFactory.setReadTimeout(300000);
        requestFactory.setWriteTimeout(300000);
        REST_TEMPLATE = new RestTemplate(requestFactory);
    }

    public static String post(String url, Object request) {
        return post(url, request, new ParameterizedTypeReference<String>() {});
    }

    public static <T> T post(String url, Object request, ParameterizedTypeReference<T> reference) {
        return post(url, request, MediaType.APPLICATION_JSON, reference);
    }

    public static <T> T postFile(String url, MultiValueMap<String, Object> request, ParameterizedTypeReference<T> reference) {
        return post(url, request, MediaType.MULTIPART_FORM_DATA, reference);
    }

    public static <T> T post(String url, Object request, MediaType mediaType, ParameterizedTypeReference<T> reference) {
        if (Objects.isNull(reference)) return null;

        String wrapperUrl = wrapperUrl(url);
        if (StringUtils.isEmpty(wrapperUrl)) return null;

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(mediaType);

        HttpEntity httpEntity = new HttpEntity(request, headers);

        try {
            return REST_TEMPLATE.exchange(wrapperUrl, HttpMethod.POST, httpEntity, reference).getBody();
        }
        catch (Exception e) {
            log.error("post error. url={} request={} cause={}", url, request, e.getMessage());
            throw new BusinessException(ErrorEnum.REST_FAIL);
        }
    }

    public static ResponseEntity<byte[]> getForEntity(String url, Map<String, String> request) {
        String wrapperUrl = wrapperUrl(url);
        if (StringUtils.isEmpty(wrapperUrl)) return null;

        try {
            ResponseEntity<byte[]> responseEntity = REST_TEMPLATE.getForEntity(wrapperUrl(wrapperUrl, request), byte[].class);
            return responseEntity;
        }
        catch (Exception e) {
            log.error("post error. url={} request={} cause={}", url, request, e.getMessage());
            throw new BusinessException(ErrorEnum.REST_FAIL);
        }
    }

    private static String wrapperUrl(String url, Map<String, String> request) {
        if (MapUtils.isEmpty(request)) return url;
        StringBuilder builder = new StringBuilder(url).append("?");
        request.forEach((key, value) -> builder.append(key).append("=").append(value).append("&"));
        builder.deleteCharAt(builder.length() - 1);
        return builder.toString();
    }

    private static String wrapperUrl(String url) {
        if (StringUtils.isEmpty(url)) return null;
        if (url.startsWith("http")) return url;
        return "http://" + url;
    }

}
